/*
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* $Id: serverlistmodel.cpp 293 2009-02-15 09:52:20Z vjousse $
*/

#include "serverlistmodel.h"
#include <QApplication>
#include <QWidget>
#include <QStyle>

ServerListModel::ServerListModel(QObject* parent)
    : QAbstractTableModel(parent)
{
}

int ServerListModel::rowCount(const QModelIndex& parent) const
{
    if (parent.isValid())
        return 0;
    
    return d.servers.count();
}

int ServerListModel::columnCount(const QModelIndex& parent) const
{
    if (parent.isValid())
        return 0;
    
    return ColumnCount;
}

Qt::ItemFlags ServerListModel::flags(const QModelIndex& index) const
{
    Qt::ItemFlags f = QAbstractTableModel::flags(index);
    if (index.isValid())
        f |= Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable;
    else
        f |= Qt::ItemIsDropEnabled;
    return f;
}

Qt::DropActions ServerListModel::supportedDropActions() const
{
    return Qt::MoveAction;
}

QVariant ServerListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
    {
        switch (section)
        {
            case ColumnName:
                return tr("Name");
            case ColumnUser:
                return tr("Username");
            case ColumnPassword:
                return tr("Password");
            case ColumnHost:
                return tr("Host");
            case ColumnPort:
                return tr("Port");
            default:
                break;
        }
    }
    return QVariant();
}

QMap<int, QVariant> ServerListModel::itemData(const QModelIndex& index) const
{
    QMap<int, QVariant> data = QAbstractTableModel::itemData(index);
    data.insert(ServerRole, index.data(ServerRole));
    return data;
}

QVariant ServerListModel::data(const QModelIndex& index, int role) const
{
    if (!index.isValid())
        return QVariant();
    
    if (index.row() >= 0 && index.row() < d.servers.count())
    {
        if (role == Qt::DisplayRole)
        {
            const Server& server = d.servers.at(index.row());
            switch (index.column())
            {
            case ColumnName:
                return server.name;
            case ColumnUser:
                return server.user;
            case ColumnPassword:
                {
                    QWidget* widget = static_cast<QWidget*>(QObject::parent());
                    return QString(server.password.length(), 
                        widget->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, 0, widget));
                }
            case ColumnHost:
                return server.host;
            case ColumnPort:
                return server.port;
            default:
                break;
            }
        }
        else if (role == Qt::CheckStateRole)
        {
            if (index.column() == 0)
                return d.servers.at(index.row()).autoConnect ? Qt::Checked : Qt::Unchecked;
        }
        else if (role == Qt::ToolTipRole)
        {
            const Server& server = d.servers.at(index.row());

            QWidget* widget = static_cast<QWidget*>(QObject::parent());
            QString password = QString(server.password.length(), 
                widget->style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter, 0, widget));

            return tr(
                "<table><tr>"
                "<td rowspan='7'><img src=':/images/icon-32.png'/>&nbsp;&nbsp;</td>"
                "<td colspan='2'><h2>%1</h2></td>"
                "</tr><tr>"
                "<td><b>Auto-connect:</b></td>"
                "<td>%2</td>"
                "</tr><tr>"
                "<td><b>Host:</b></td>"
                "<td>%3</td>"
                "</tr><tr>"
                "<td><b>Port:</b></td>"
                "<td>%4</td>"
                "</tr><tr>"
                "<td><b>Username:</b></td>"
                "<td>%5</td>"
                "</tr><tr>"
                "<td><b>Password:</b></td>"
                "<td>%6</td>"
                "</tr></table>"
                )
                .arg(server.name)
                .arg(server.autoConnect ? tr("Yes") : tr("No"))
                .arg(server.host)
                .arg(server.port)
                .arg(server.user)
                .arg(password);
        }
        else if (role == ServerRole)
        {
            return d.servers.at(index.row());
        }
    }
    
    return QVariant();
}

bool ServerListModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if (!index.isValid())
        return false;
    
    if (index.row() >= 0 && index.row() < d.servers.count())
    {
        if (role == Qt::CheckStateRole)
        {
            if (index.column() == 0)
            {
                d.servers[index.row()].autoConnect = (value.toInt() == Qt::Checked);
                emit dataChanged(index, index);
            }
        }
        else if (role == ServerRole)
        {
            d.servers.replace(index.row(), value.value<Server>());
            emit dataChanged(index, index);
        }
    }

    return true;
}

bool ServerListModel::insertRows(int row, int count, const QModelIndex& parent)
{
    if (count < 1 || row < 0 || row > rowCount(parent))
        return false;

    beginInsertRows(QModelIndex(), row, row + count - 1);

    for (int i = 0; i < count; ++i)
        d.servers.insert(row, Server());

    endInsertRows();

    return true;
}

bool ServerListModel::removeRows(int row, int count, const QModelIndex& parent)
{
    if (count <= 0 || row < 0 || (row + count) > rowCount(parent))
        return false;

    beginRemoveRows(QModelIndex(), row, row + count - 1);

    for (int i = 0; i < count; ++i)
        d.servers.removeAt(row);

    endRemoveRows();

    return true;
}

bool ServerListModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
{
    Q_UNUSED(column);
    return QAbstractTableModel::dropMimeData(data, action, row, 0, parent);
}

ServerList ServerListModel::servers() const
{
    return d.servers;
}

void ServerListModel::addServers(const ServerList& servers)
{
    if (!servers.isEmpty())
    {
        beginInsertRows(QModelIndex(), rowCount(), rowCount() + servers.count() - 1);
        d.servers += servers;
        endInsertRows();
    }
}
